#ifndef __RMATH_H__
#define __RMATH_H__

#include <math.h>
#include <stdint.h>

/* fast exponent algorithm for `double` */
static inline double rmath_pow_d64(double a, int64_t n)
{
	double r = 1.0;

	while (n)
	{
		if (n & 1)
			r *= a;

		a *= a;
		n >>= 1;
	}

	return r;
}

/* fast exponent algorithm for `int64_t` */
static inline int64_t rmath_pow_i64(int64_t a, int64_t n)
{
	int64_t r = 1;

	while (n)
	{
		if (n & 1)
			r *= a;

		a *= a;
		n >>= 1;
	}

	return r;
}

/* currently I have no algorithms can be applied to `double` and `double`, so call the library */
static inline double rmath_pow_d64_2(double a, double b)
{
	return pow(a, b);
}

static inline uint32_t rmath_hash_i64(register int64_t key)
{
	register uint32_t msb = (key & 0xFFFFFFFF00000000) >> 32;
	register uint32_t lsb = (key & 0x00000000FFFFFFFF) >>  0;
	return msb ^ lsb;
}

static inline uint32_t rmath_hash_d64(double key)
{
	return rmath_hash_i64(*(int64_t *)(&key));
}

static inline uint32_t rmath_hash_str(register const char *s, register int len)
{
	register uint32_t hash = 0;
	while (len--) hash = hash * 131 + (*s++);
	return hash;
}

#endif /* __RMATH_H__ */
